package simco.framework.gui.services.data;

import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractListModel;

import simco.framework.gui.graph.ConnectingLine;
import simco.framework.gui.graph.Intermediate;
import simco.framework.gui.graph.ProvidedInterface;
import simco.framework.gui.graph.UsedComponent;
import simco.framework.gui.graph.iface.Selectable;
import simco.framework.gui.graph.supp.ComponentType;

/**
 * Tato trida reprezentuje datovy model, ve kterem
 * jsou uchovany informace o prave vybranem objektu.
 * 
 * Slouzi jako datovy model pro JList, do ktereho
 * jsou vypisovany informace o aktualne vybranem
 * objektu.
 * 
 * @author Matej Prokop, mythge@students.zcu.cz
 */
public class InfoModel extends AbstractListModel
{
	/**
	 * Obsah okna s informacemi o vybranem objektu.
	 * Kazdy list seznamu reprezentuje jeden radek
	 * okna s informacemi.
	 */
	private List<String> contentList;
	
	/**
	 * Typ vybraneho objektu
	 */
	private SelectedObjectType selectedObjectType;
	
	/**
	 * Identifikator vybraneho objektu
	 */
	private long selectedObjectId;
	
	/**
	 * Vytvori novy objekt, ktery slouzi jako
	 * datovy model pro JList zobrazujici
	 * informace o vybranem objektu
	 */
	public InfoModel() 
	{
		this.contentList = new ArrayList<String>();
		this.selectedObjectType = SelectedObjectType.NOTHING;;
	}

	/**
	 * Nastavi aktualne oznaceny objekt
	 * 
	 * @param selected reference na aktualne vybrany objekt
	 */
	public void setSelectedObject(Selectable selected)
	{
		if(selected == null)
		{
			this.selectedObjectType = SelectedObjectType.NOTHING;
			
			synchronized (this) 
			{
				if(contentList.size() > 0)
				{
					fireIntervalRemoved(this, 0, contentList.size() - 1);
				}
				
				contentList.clear();
			}
		}
		else
		{
			if (selected instanceof ConnectingLine)
			{
				selectedObjectType = SelectedObjectType.LINE;
				ConnectingLine new_name = (ConnectingLine) selected;	
				selectedObjectId = new_name.getId();
			}
			else if (selected instanceof ProvidedInterface) 
			{
				selectedObjectType = SelectedObjectType.INTERFACE;
				ProvidedInterface new_name = (ProvidedInterface) selected;
				selectedObjectId = new_name.getId();
			}
			else if (selected instanceof Intermediate) 
			{
				selectedObjectType = SelectedObjectType.INTERMEDIATE;
				Intermediate new_name = (Intermediate) selected;
				selectedObjectId = new_name.getId();
			}
			else if (selected instanceof UsedComponent)
			{				
				UsedComponent new_name = (UsedComponent) selected;
				if(new_name.getType() == ComponentType.SIMULATION)
				{
					selectedObjectType = SelectedObjectType.SIM_COMP;
				}
				else 
				{
					selectedObjectType = SelectedObjectType.REAL_COMP;
				}
				selectedObjectId = new_name.getId();
			}
		}
	}
	
	
	/**
	 * Vrati typ aktualne oznaceneho objektu
	 * 
	 * @return typ aktualne oznaceneho objektu
	 */
	public SelectedObjectType getSelectedObjectType() 
	{
		return selectedObjectType;
	}

	/**
	 * Vrati identifikator aktualne oznaceneho objektu
	 * @return identifikator aktualne oznaceneho objektu
	 */
	public long getSelectedObjectId() 
	{
		return selectedObjectId;
	}

	/**
	 * Aktualizuje zobrazovani obsah (data) modelu. Prepise zobrazovany
	 * obsah seznamem (listem) prijaty jako parametr.
	 * 
	 * @param updatedList novy obsah datoveho modelu
	 */
	public synchronized void updateList(List<String> updatedList)
	{	
		if(selectedObjectType == null)
		{
			return;
		}
		
			if(contentList.size() == updatedList.size())
			{			
				if(!updatedList.isEmpty() && contentList.get(0) != updatedList.get(0))
				{
					changeList(updatedList);
					return;
				}
			}
			
			int lastSize = contentList.size();
			
			for(int i = contentList.size(); i < updatedList.size(); i++ )
			{
				this.contentList.add(updatedList.get(i));
			}
			
		fireIntervalAdded(this, lastSize, updatedList.size() - 1);
	}
	
	/**
	 * Odstrani vsechny polozky v datovem modelu a nahradi je 
	 * polozkami v prijatem seznamu. 
	 * 
	 * @param updatedList novy zobrazovany seznam
	 */
	public synchronized void changeList(List<String> newList)
	{		
		if(contentList.size() > 0)
		{
			fireIntervalRemoved(this, 0, contentList.size() - 1);
		}
		
		contentList.clear();
		
		for(String s : newList)
		{
			contentList.add(s);
		}
		
		if(this.contentList.isEmpty())
		{
			return;
		}			
		
		fireIntervalAdded(this, 0, this.contentList.size() - 1);			
	}
	
	@Override
	public Object getElementAt(int index) 
	{
		return contentList.get(index);
	}

	@Override
	public synchronized int getSize() 
	{		
		return contentList.size();
	}
	
}
